package com.example.tank;

import com.example.tank.entity.Bullet;
import com.example.tank.entity.Enemy;
import com.example.tank.entity.Player;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class GamePanel extends JPanel implements Runnable {
    private static final int PANEL_WIDTH = 800;
    private static final int PANEL_HEIGHT = 600;
    
    private Player player;
    private List<Enemy> enemies;
    private List<Bullet> playerBullets;
    private List<Bullet> enemyBullets;
    private boolean isRunning;
    private Thread gameThread;
    private boolean upPressed;
    private boolean downPressed;
    private boolean leftPressed;
    private boolean rightPressed;
    
    public GamePanel() {
        setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        
        initGame();
        setupKeyListener();
    }
    
    private void initGame() {
        player = new Player(100, 500);
        enemies = new ArrayList<>();
        playerBullets = new ArrayList<>();
        enemyBullets = new ArrayList<>();
        
        // Add some initial enemies
        enemies.add(new Enemy(400, 100));
        enemies.add(new Enemy(600, 200));
        enemies.add(new Enemy(300, 300));
        
        isRunning = true;
    }
    
    private void setupKeyListener() {
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                switch (keyCode) {
                    case KeyEvent.VK_UP:
                    case KeyEvent.VK_W:
                        upPressed = true;
                        break;
                    case KeyEvent.VK_DOWN:
                    case KeyEvent.VK_S:
                        downPressed = true;
                        break;
                    case KeyEvent.VK_LEFT:
                    case KeyEvent.VK_A:
                        leftPressed = true;
                        break;
                    case KeyEvent.VK_RIGHT:
                    case KeyEvent.VK_D:
                        rightPressed = true;
                        break;
                    case KeyEvent.VK_SPACE:
                        shoot();
                        break;
                }
            }
            
            @Override
            public void keyReleased(KeyEvent e) {
                int keyCode = e.getKeyCode();
                switch (keyCode) {
                    case KeyEvent.VK_UP:
                    case KeyEvent.VK_W:
                        upPressed = false;
                        break;
                    case KeyEvent.VK_DOWN:
                    case KeyEvent.VK_S:
                        downPressed = false;
                        break;
                    case KeyEvent.VK_LEFT:
                    case KeyEvent.VK_A:
                        leftPressed = false;
                        break;
                    case KeyEvent.VK_RIGHT:
                    case KeyEvent.VK_D:
                        rightPressed = false;
                        break;
                }
            }
        });
    }
    
    private void shoot() {
        int bulletX = player.getX() + player.getBounds().width/2;
        int bulletY = player.getY() + player.getBounds().height/2;
        playerBullets.add(new Bullet(bulletX, bulletY, player.getDirection()));
    }

    private void enemyShoot(Enemy enemy) {
        int bulletX = enemy.getX() + 20; // Half of enemy width
        int bulletY = enemy.getY() + 20; // Half of enemy height
        enemyBullets.add(new Bullet(bulletX, bulletY, enemy.getDirection()));
    }
    
    @Override
    public void addNotify() {
        super.addNotify();
        gameThread = new Thread(this);
        gameThread.start();
    }
    
    @Override
    public void run() {
        while (isRunning) {
            update();
            repaint();
            
            try {
                Thread.sleep(16); // Approximately 60 FPS
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
    private void update() {
        // 玩家移动，带碰撞检测
        if (upPressed) {
            attemptPlayerMove(0, -player.getSpeed());
        }
        if (downPressed) {
            attemptPlayerMove(0, player.getSpeed());
        }
        if (leftPressed) {
            attemptPlayerMove(-player.getSpeed(), 0);
        }
        if (rightPressed) {
            attemptPlayerMove(player.getSpeed(), 0);
        }

        // Update player bullets
        Iterator<Bullet> playerBulletIterator = playerBullets.iterator();
        while (playerBulletIterator.hasNext()) {
            Bullet bullet = playerBulletIterator.next();
            bullet.update();
            // Remove bullets that are off screen
            if (bullet.isOffScreen(PANEL_WIDTH, PANEL_HEIGHT)) {
                playerBulletIterator.remove();
                continue;
            }
            // Check for bullet collisions with enemies
            Iterator<Enemy> enemyIterator = enemies.iterator();
            while (enemyIterator.hasNext()) {
                Enemy enemy = enemyIterator.next();
                if (enemy.isHit(bullet.getBounds())) {
                    enemyIterator.remove();
                    playerBulletIterator.remove();
                    break;
                }
            }
        }

        // Update enemy bullets
        Iterator<Bullet> enemyBulletIterator = enemyBullets.iterator();
        while (enemyBulletIterator.hasNext()) {
            Bullet bullet = enemyBulletIterator.next();
            bullet.update();
            // Remove bullets that are off screen
            if (bullet.isOffScreen(PANEL_WIDTH, PANEL_HEIGHT)) {
                enemyBulletIterator.remove();
                continue;
            }
            // Check for bullet collisions with player
            if (player.isHit(bullet.getBounds())) {
                // Here you can add game over logic
                System.out.println("Game Over!");
                isRunning = false;
                enemyBulletIterator.remove();
                break;
            }
        }

        // Update enemies和碰撞检测
        for (Enemy enemy : enemies) {
            attemptEnemyMove(enemy);
            if (enemy.shouldShoot()) {
                enemyShoot(enemy);
            }
        }
    }

    // 玩家移动尝试，带碰撞检测
    private void attemptPlayerMove(int dx, int dy) {
        Rectangle nextBounds = new Rectangle(player.getX() + dx, player.getY() + dy, 40, 40);
        for (Enemy enemy : enemies) {
            if (nextBounds.intersects(enemy.getBounds())) {
                return; // 有碰撞则不移动
            }
        }
        // 边界检测
        if (nextBounds.x < 0 || nextBounds.y < 0 || nextBounds.x + nextBounds.width > PANEL_WIDTH || nextBounds.y + nextBounds.height > PANEL_HEIGHT) {
            return;
        }
        player.setX(player.getX() + dx);
        player.setY(player.getY() + dy);
        // 设置方向
        if (dx < 0) player.setDirection(3);
        else if (dx > 0) player.setDirection(1);
        else if (dy < 0) player.setDirection(0);
        else if (dy > 0) player.setDirection(2);
    }

    // 敌人移动尝试，带碰撞检测
    private void attemptEnemyMove(Enemy enemy) {
        int newX = enemy.getX();
        int newY = enemy.getY();
        int speed = enemy.getSpeed();
        int direction = enemy.getDirection();
        switch (direction) {
            case 0: newY -= speed; break;
            case 1: newX += speed; break;
            case 2: newY += speed; break;
            case 3: newX -= speed; break;
        }
        Rectangle nextBounds = new Rectangle(newX, newY, 40, 40);
        // 检查与玩家碰撞
        if (nextBounds.intersects(player.getBounds())) {
            enemy.setDirection((int) (Math.random() * 4));
            enemy.setMoveCounter(0);
            return;
        }
        // 检查与其他敌人碰撞
        for (Enemy other : enemies) {
            if (other != enemy && nextBounds.intersects(other.getBounds())) {
                enemy.setDirection((int) (Math.random() * 4));
                enemy.setMoveCounter(0);
                return;
            }
        }
        // 边界检测
        if (nextBounds.x < 0 || nextBounds.y < 0 || nextBounds.x + nextBounds.width > PANEL_WIDTH || nextBounds.y + nextBounds.height > PANEL_HEIGHT) {
            enemy.setDirection((int) (Math.random() * 4));
            enemy.setMoveCounter(0);
            return;
        }
        enemy.setX(newX);
        enemy.setY(newY);
        enemy.setMoveCounter(enemy.getMoveCounter() + 1);
        if (enemy.getMoveCounter() >= enemy.getChangeDirectionTime() || Math.random() < 0.02) {
            enemy.setDirection((int) (Math.random() * 4));
            enemy.setMoveCounter(0);
        }
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        // Draw player
        player.draw(g);
        
        // Draw player bullets
        for (Bullet bullet : playerBullets) {
            bullet.draw(g);
        }

        // Draw enemy bullets
        g.setColor(Color.RED); // Set color for enemy bullets
        for (Bullet bullet : enemyBullets) {
            bullet.draw(g);
        }
        
        // Draw enemies
        for (Enemy enemy : enemies) {
            enemy.draw(g);
        }
        
        // Draw game info
        g.setColor(Color.WHITE);
        g.drawString("Enemies remaining: " + enemies.size(), 20, 30);
        g.drawString("Use WASD or arrow keys to move and SPACE to shoot", 20, PANEL_HEIGHT - 20);
        if (!isRunning) {
            g.setColor(Color.RED);
            g.setFont(new Font("Arial", Font.BOLD, 48));
            g.drawString("GAME OVER", PANEL_WIDTH/2 - 120, PANEL_HEIGHT/2);
        }
    }
}